Spring Cloud Netflix Eureka
1. 개요
1. 개요
Spring Cloud Netflix Eureka는 Netflix, Inc.가 오픈소스로 공개한 서비스 디스커버리 도구로, Spring Cloud 프로젝트의 핵심 구성 요소 중 하나이다. 이는 마이크로서비스 아키텍처 환경에서 각 서비스 인스턴스의 위치(네트워크 주소)를 동적으로 등록하고 조회할 수 있는 서비스 레지스트리를 제공한다. Eureka를 사용하면 클라이언트 애플리케이션이 하드코딩된 URL 없이도 필요한 서비스를 찾아 호출할 수 있으며, 이는 클라우드 네이티브 애플리케이션 구축의 기반이 된다.
Eureka는 기본적으로 클라이언트-서버 모델을 따른다. Eureka 서버는 서비스 레지스트리의 중앙 허브 역할을 하며, 각 마이크로서비스인 Eureka 클라이언트는 시작 시 자신의 메타데이터를 서버에 등록한다. 이후 클라이언트는 주기적으로 하트비트를 보내 자신의 가용 상태를 갱신한다. 다른 서비스는 Eureka 클라이언트를 통해 레지스트리에서 목표 서비스의 인스턴스 목록을 조회하고, 내장된 로드 밸런서를 사용해 그 중 하나를 선택하여 통신한다.
이 도구는 서비스 인스턴스의 상태 변화에 자동으로 대응한다. 인스턴스가 정상적으로 종료되면 등록 취소 요청을 보내 레지스트리에서 제거되지만, 장애로 인해 하트비트가 중단되면 Eureka 서버는 일정 시간 후 해당 인스턴스를 레지스트리에서 제거한다. 이러한 자동화된 등록과 제거 메커니즘은 서비스의 확장, 축소, 장애 복구를 용이하게 하여 전체 시스템의 탄력성과 가용성을 높인다.
Spring Cloud Netflix Eureka는 아파치 라이선스 2.0 하에 배포되어 자유롭게 사용 및 수정할 수 있으며, Spring Boot의 자동 구성 기능과 결합되어 매우 간편한 설정과 통합을 가능하게 한다. 이는 마이크로서비스 간의 통신 인프라를 단순화하고, 클라우드 컴퓨팅 환경에 적합한 애플리케이션 개발을 지원하는 데 크게 기여했다.
2. 주요 개념
2. 주요 개념
2.1. Eureka 서버
2.1. Eureka 서버
Eureka 서버는 Spring Cloud Netflix 프로젝트의 핵심 구성 요소로서, 마이크로서비스 아키텍처에서 서비스 디스커버리 패턴을 구현하는 데 사용되는 서비스 레지스트리이다. 이 서버는 모든 실행 중인 마이크로서비스 인스턴스의 네트워크 위치 정보를 중앙에서 저장하고 관리하는 역할을 담당한다. 각 서비스 인스턴스는 시작 시 자신의 정보를 Eureka 서버에 등록하며, 서비스 간 통신이 필요할 때 클라이언트는 이 서버를 조회하여 대상 서비스의 실제 위치를 얻는다.
Eureka 서버는 자바 기반의 독립 실행형 웹 애플리케이션으로 배포될 수 있으며, 스프링 부트의 자동 구성 기능을 통해 간단한 설정으로 빠르게 구동할 수 있다. 기본적으로 내장된 웹 인터페이스를 제공하여 등록된 서비스 인스턴스 목록과 그 상태를 실시간으로 확인할 수 있다. 이는 운영 중인 분산 시스템의 건강 상태를 모니터링하는 데 유용한 도구가 된다.
고가용성을 위해 Eureka 서버는 피어 투 피어 복제 모델을 지원한다. 여러 대의 Eureka 서버 인스턴스를 서로 등록하여 클러스터를 구성하면, 한 서버에 등록된 서비스 정보가 동료 서버들에게 복제된다. 이렇게 함으로써 단일 장애점을 제거하고 시스템의 내결함성을 높일 수 있다. 각 Eureka 서버는 동시에 다른 서버의 Eureka 클라이언트 역할도 수행한다.
Eureka 서버의 운영은 비교적 가볍고 REST 기반의 프로토콜을 사용한다. 서비스 인스턴스는 정기적으로 하트비트를 보내 자신의 생존을 알리고, 일정 시간 동안 하트비트가 없는 인스턴스는 레지스트리에서 자동으로 제거된다. 이러한 자가 치유 메커니즘을 통해 시스템은 실패한 인스턴스를 지속적으로 정리하고, 클라이언트가 항상 정상적인 서비스 인스턴스 목록을 받을 수 있도록 보장한다.
2.2. Eureka 클라이언트
2.2. Eureka 클라이언트
Eureka 클라이언트는 Spring Cloud Netflix Eureka 생태계에서 서비스를 제공하는 개별 마이크로서비스 인스턴스를 의미한다. 이 클라이언트는 애플리케이션에 내장되어 실행되며, 시작 시 자신의 네트워크 위치(호스트, 포트, 상태 페이지 URL, 홈페이지 URL 등)를 Eureka 서버에 등록한다. 또한 주기적으로 서버에 하트비트를 전송하여 자신이 활성 상태임을 알린다.
주요 역할은 서비스 등록과 서비스 발견이다. 등록 과정을 통해 클라이언트는 자신을 서비스 레지스트리에 기록한다. 발견 과정에서는 Eureka 서버에 질의하여 필요한 다른 서비스의 인스턴스 목록을 가져온다. 이 목록은 클라이언트 측에 캐싱되며, 주기적으로 갱신되어 최신 상태를 유지한다. 이를 통해 클라이언트는 하드코딩된 URL 없이도 동적으로 서비스 위치를 찾아내고 통신할 수 있다.
Eureka 클라이언트는 Spring Boot 애플리케이션에 @EnableEurekaClient 어노테이션을 추가하거나 spring-cloud-starter-netflix-eureka-client 의존성을 포함하여 쉽게 구성할 수 있다. 설정 파일(application.yml 또는 application.properties)을 통해 자신의 애플리케이션 이름, Eureka 서버의 위치, 갱신 주기 등을 정의한다. 내부적으로는 REST API를 사용하여 Eureka 서버와 통신한다.
이 클라이언트는 서비스 디스커버리 패턴을 구현함으로써 시스템의 탄력성과 확장성을 높인다. 서비스 인스턴스가 추가되거나 제거될 때 Eureka 서버를 통해 자동으로 인식되므로, 로드 밸런싱과 장애 조치를 보다 유연하게 처리할 수 있는 기반을 제공한다.
2.3. 서비스 등록
2.3. 서비스 등록
서비스 등록은 Eureka 클라이언트가 자신의 인스턴스 정보를 Eureka 서버에 알려 레지스트리에 추가하는 과정이다. 마이크로서비스 애플리케이션이 시작될 때, 구성된 Eureka 클라이언트는 자동으로 서비스 등록 절차를 시작한다. 이때 등록되는 정보에는 서비스의 고유 ID, 호스트명, 포트 번호, 상태 페이지 URL, 헬스 체크 URL 등이 포함된다.
등록 절차는 클라이언트가 서버의 /eureka/apps/{서비스명} API 엔드포인트에 자신의 인스턴스 메타데이터를 포함한 POST 요청을 보내는 방식으로 이루어진다. 성공적으로 등록되면, 해당 서비스 인스턴스는 Eureka 서버의 내부 레지스트리에 저장되어 다른 클라이언트들이 조회할 수 있는 상태가 된다. 이 레지스트리는 서비스 이름을 키로 하여 해당 서비스의 모든 활성 인스턴스 목록을 유지 관리한다.
등록 후에도 인스턴스는 정기적으로 하트비트를 서버에 보내 자신이 여전히 활성 상태임을 증명한다. 만약 일정 시간 동안 하트비트가 수신되지 않으면, 서버는 해당 인스턴스를 레지스트리에서 제거한다. 이렇게 서비스 등록과 주기적 갱신을 통해 Eureka는 실시간으로 변경되는 마이크로서비스 환경의 동적 인스턴스 정보를 정확하게 반영할 수 있다.
2.4. 서비스 발견
2.4. 서비스 발견
서비스 발견은 마이크로서비스 아키텍처의 핵심 패턴 중 하나로, 네트워크 상의 서비스 인스턴스가 서로의 위치를 동적으로 찾아내고 통신할 수 있도록 하는 메커니즘이다. Spring Cloud Netflix Eureka는 이 서비스 발견 기능을 구현하는 서비스 레지스트리의 역할을 수행한다. 각 마이크로서비스는 시작 시 자신의 네트워크 위치(호스트, 포트 등)를 Eureka 서버에 등록하고, 다른 서비스를 호출해야 할 때는 레지스트리에서 대상 서비스의 사용 가능한 인스턴스 목록을 조회하여 가져온다.
이러한 방식은 전통적인 정적 구성 방식의 문제점을 해결한다. 클라우드 네이티브 환경에서는 서비스 인스턴스가 자주 생성되고 소멸되며, 그 위치(IP 주소)도 동적으로 변경될 수 있다. Eureka를 사용하면 클라이언트 애플리케이션이 하드코딩된 서버 목록을 유지할 필요 없이, 항상 현재 가용한 서비스 인스턴스의 정보를 Eureka 서버로부터 얻을 수 있다. 이는 시스템의 탄력성과 확장성을 크게 향상시킨다.
Eureka 클라이언트는 서비스 발견을 위한 두 가지 주요 기능을 내장하고 있다. 하나는 서비스 등록이며, 다른 하나는 서비스 조회이다. 클라이언트는 애플리케이션 시작 시 자동으로 자신을 Eureka 서버에 등록하고, 주기적으로 하트비트를 보내 자신의 상태를 갱신한다. 동시에, 다른 서비스를 호출할 필요가 있을 때는 내장된 로드 밸런서를 통해 Eureka 서버로부터 최신의 서비스 인스턴스 목록을 가져와 그 중 하나를 선택하여 요청을 전달한다. 이 과정은 대부분 애플리케이션 코드에 투명하게 통합되어 개발자가 직접 네트워크 위치를 관리할 부담을 줄여준다.
서비스 발견은 분산 시스템의 복잡성을 관리하는 데 필수적이며, Eureka는 Spring Boot와의 긴밀한 통합을 통해 자바 생태계에서 이 패턴을 쉽게 적용할 수 있게 한다. 이를 통해 개발팀은 서비스 간 통신의 기술적 복잡성보다 비즈니스 로직 개발에 더 집중할 수 있게 된다.
2.5. 헬스 체크
2.5. 헬스 체크
Eureka 클라이언트는 등록된 서비스 인스턴스의 가용성을 지속적으로 확인하기 위해 헬스 체크 메커니즘을 사용한다. 이는 서비스 레지스트리에 등록된 정보가 실제 서비스 상태를 정확히 반영하도록 보장하는 핵심 기능이다.
헬스 체크의 기본 원리는 Eureka 클라이언트가 주기적으로 Eureka 서버로 하트비트(또는 갱신 요청)를 보내 자신이 살아있음을 알리는 것이다. 이 주기는 일반적으로 30초로 설정된다. 서버는 일정 시간 동안 특정 인스턴스로부터 하트비트를 받지 못하면, 해당 인스턴스를 장애 상태로 간주하고 레지스트리에서 제거하기 시작한다. 이 제거까지의 대기 시간은 기본적으로 90초로, 세 번의 하트비트 주기를 놓친 후에 발생한다.
보다 정교한 상태 판단을 위해, Eureka는 Actuator 엔드포인트와 통합된 애플리케이션 수준의 헬스 체크를 지원할 수 있다. 클라이언트는 애플리케이션 내부의 헬스 정보를 기반으로 서버에 자신의 상태를 'UP', 'OUT_OF_SERVICE' 등으로 보고할 수 있다. 이를 통해 네트워크 연결은 유지되지만 내부적으로 문제가 있는 서비스 인스턴스를 트래픽에서 선별적으로 제외시키는 것이 가능해진다.
이러한 지속적인 헬스 체크와 상태 갱신을 통해, Eureka 서버는 실시간으로 유효한 서비스 인스턴스 목록을 유지한다. 다른 마이크로서비스들은 이 목록을 조회하여 항상 정상 동작하는 인스턴스로만 요청을 라우팅할 수 있게 되어, 시스템 전체의 견고성과 가용성이 향상된다.
3. 아키텍처
3. 아키텍처
3.1. 클라이언트-서버 모델
3.1. 클라이언트-서버 모델
Spring Cloud Netflix Eureka는 전형적인 클라이언트-서버 모델을 기반으로 구축된다. 이 모델에서 Eureka 서버는 중앙 집중식 서비스 레지스트리의 역할을 하며, 모든 마이크로서비스 인스턴스인 Eureka 클라이언트는 이 서버에 자신을 등록하고 다른 서비스의 위치 정보를 조회한다.
서버는 클라이언트로부터 받은 등록 정보를 메모리에 저장하고 관리하며, 주기적인 하트비트를 통해 각 서비스 인스턴스의 가용 상태를 확인한다. 클라이언트는 애플리케이션 시작 시 서버에 자신의 네트워크 위치(호스트, 포트, 상태 페이지 URL 등)를 등록하고, 정기적으로 하트비트를 전송하여 등록을 갱신한다.
이러한 구조는 서비스 디스커버리 패턴을 구현하는 핵심이다. 클라이언트는 필요한 서비스를 하드코딩된 엔드포인트 없이도 Eureka 서버에 질의하여 동적으로 찾아낼 수 있다. 결과적으로 마이크로서비스 아키텍처에서 서비스의 확장, 축소, 장애 복구 시 발생하는 네트워크 위치 변경 문제를 투명하게 해결하며, 클라이언트 사이드 로드 밸런싱을 가능하게 한다.
3.2. 피어링 및 고가용성
3.2. 피어링 및 고가용성
유레카 서버는 단일 장애점(Single Point of Failure)을 방지하고 고가용성을 확보하기 위해 피어링(Peering) 구조를 지원한다. 여러 유레카 서버 인스턴스를 서로 등록하여 피어 노드로 구성하면, 이들은 서로의 레지스트리 정보를 복제하여 공유한다. 이는 클러스터링의 한 형태로, 하나의 서버에 장애가 발생하더라도 다른 피어 서버가 서비스 디스커버리 기능을 계속 제공할 수 있도록 한다.
피어링 구성은 각 유레카 서버의 설정 파일에서 다른 피어 서버들의 URL을 명시함으로써 이루어진다. 예를 들어, 두 대의 유레카 서버를 피어로 구성할 경우, 각 서버는 상대방을 자신의 피어 목록에 등록한다. 서비스 인스턴스가 하나의 서버에 등록되면, 그 정보는 구성된 피어 서버들로 전파된다. 이를 통해 모든 피어 서버는 거의 동일한 서비스 인스턴스 정보를 유지하게 되어, 클라이언트가 어떤 피어 서버에 연결하더라도 전체 서비스 목록을 조회할 수 있다.
고가용성 아키텍처를 설계할 때는 일반적으로 최소 두 개 이상의 지역에 걸쳐 피어 서버를 분산 배포하는 것이 권장된다. 이는 데이터센터 전체에 장애가 발생하는 상황에도 서비스 레지스트리의 가용성을 유지하기 위함이다. 스프링 클라우드 기반의 마이크로서비스 애플리케이션에서는 클라이언트 측에도 여러 유레카 서버의 주소를 목록으로 제공하여, 첫 번째 서버에 연결 실패 시 자동으로 다음 서버로 폴백(fallback)하도록 구성할 수 있다.
이러한 피어링 메커니즘은 분산 시스템에서 데이터의 일관성과 가용성 사이의 균형을 유지하는 데 기여한다. 유레카는 AP 시스템의 특성을 가지며, 가용성과 분할 내성(Partition Tolerance)을 우선시한다. 따라서 네트워크 분할 상황에서도 서비스는 등록 및 조회가 가능하도록 유지되며, 짧은 시간 동안 피어 간 레지스트리 데이터의 불일치가 발생할 수 있다.
4. 구성 요소
4. 구성 요소
4.1. Eureka 서버 설정
4.1. Eureka 서버 설정
Eureka 서버는 Spring Cloud Netflix 프로젝트의 핵심 구성 요소로서, 마이크로서비스 인스턴스의 등록 정보를 저장하고 관리하는 서비스 레지스트리이다. 서버를 설정하는 주요 방법은 독립 실행형 스프링 부트 애플리케이션으로 구동하는 것이다. 이를 위해 메인 애플리케이션 클래스에 @EnableEurekaServer 어노테이션을 추가하면, 해당 애플리케이션이 Eureka 서버의 역할을 수행하게 된다.
서버의 구체적인 동작 방식은 application.yml 또는 application.properties 파일을 통해 구성한다. 주요 설정 항목으로는 서버가 수신 대기할 포트 번호, 다른 Eureka 서버와의 피어링을 위한 상대방 서버 목록, 클라이언트로부터의 등록 요청을 수락할지 여부, 그리고 서비스 레지스트리에 등록된 정보를 클라이언트에게 캐싱하여 제공하는 시간 간격 등이 있다. 특히, 단일 서버 구성보다는 두 대 이상의 서버를 상호 피어링하여 구성하는 것이 고가용성을 보장하는 표준적인 방법이다.
Eureka 서버는 내부적으로 REST API를 제공하여 Eureka 클라이언트의 등록, 갱신, 조회 요청을 처리한다. 또한, 서버는 정기적인 헬스 체크를 통해 등록된 서비스 인스턴스의 상태를 모니터링하고, 일정 시간 동안 하트비트 신호를 받지 못한 인스턴스를 레지스트리에서 자동으로 제거하는 기능을 갖추고 있다. 이러한 설정들은 마이크로서비스 아키텍처의 탄력성과 자가 치유 능력을 구현하는 데 기여한다.
4.2. Eureka 클라이언트 설정
4.2. Eureka 클라이언트 설정
Eureka 클라이언트는 Spring Boot 애플리케이션에 spring-cloud-starter-netflix-eureka-client 의존성을 추가하여 간단히 설정할 수 있다. 이 의존성을 추가하면 애플리케이션은 자동으로 Eureka 클라이언트로 동작하며, 애플리케이션 시작 시 지정된 Eureka 서버에 자신을 등록하고, 서버로부터 다른 서비스의 위치 정보를 주기적으로 조회한다.
주요 설정은 application.yml 또는 application.properties 파일을 통해 이루어진다. 가장 핵심적인 설정은 Eureka 서버의 위치를 지정하는 eureka.client.service-url.defaultZone이다. 또한, 애플리케이션의 고유한 서비스명을 spring.application.name으로 정의하는 것이 중요하다. 이 이름은 서비스 디스커버리 과정에서 다른 클라이언트가 해당 서비스를 찾는 키로 사용된다.
클라이언트의 동작을 세밀하게 제어하기 위한 추가 설정도 제공된다. 예를 들어, 서버에 등록된 자신의 정보를 갱신하는 하트비트(갱신) 간격, 서비스 정보를 캐시하는 주기, 초기 등록 실패 시 재시도 여부 등을 구성할 수 있다. Spring Cloud Netflix는 이러한 설정에 합리적인 기본값을 제공하므로, 간단한 경우 최소한의 설정만으로도 서비스 디스커버리를 활용할 수 있다.
설정 항목 (예시) | 설명 | 기본값 예시 |
|---|---|---|
| Eureka 서버의 URL |
|
| 서비스의 고유 식별자 | (설정 필수) |
| 하트비트(갱신) 전송 간격 | 30 |
| 레지스트리 정보 갱신 간격 | 30 |
| Eureka 클라이언트 기능 활성화 여부 | true |
5. 동작 방식
5. 동작 방식
5.1. 등록 절차
5.1. 등록 절차
등록 절차는 Eureka 클라이언트가 자신의 정보를 Eureka 서버에 알려 서비스 레지스트리에 추가되는 과정이다. 이는 서비스 디스커버리의 첫 번째 단계로, 서비스 인스턴스가 시작된 후 자동으로 수행된다.
클라이언트는 애플리케이션 구동 시 구성된 Eureka 서버의 주소로 등록 요청을 보낸다. 요청에는 서비스의 고유 식별자인 인스턴스 ID, 호스트명, IP 주소, 포트 번호, 상태 페이지 URL, 헬스 체크 URL 등의 메타데이터가 포함된다. 서버는 이 정보를 받아 내부 레지스트리에 저장하고, 다른 클라이언트들이 조회할 수 있도록 만든다.
등록이 성공하면, 클라이언트는 주기적으로 서버에 하트비트(갱신 요청)를 보내 자신이 활성 상태임을 알린다. 만일 일정 시간 동안 하트비트가 수신되지 않으면, 서버는 해당 인스턴스를 장애 상태로 판단하고 레지스트리에서 제거하는 제거 절차를 시작한다. 이렇게 지속적인 등록과 갱신을 통해 Eureka는 실시간으로 변하는 마이크로서비스 환경의 서비스 목록을 정확하게 유지한다.
5.2. 갱신(하트비트) 절차
5.2. 갱신(하트비트) 절차
Eureka 클라이언트는 Eureka 서버에 성공적으로 등록된 후에도 지속적으로 자신의 상태를 알리기 위해 정기적으로 하트비트를 전송한다. 이 하트비트는 기본적으로 30초 간격으로 수행되며, 이를 통해 서버는 해당 서비스 인스턴스가 여전히 활성 상태임을 인지한다. 이 주기적인 갱신 절차는 서비스 레지스트리의 정보를 최신 상태로 유지하는 데 핵심적인 역할을 한다.
Eureka 서버는 각 등록된 인스턴스로부터 하트비트를 기다리며, 설정된 임계 시간 내에 하트비트를 수신하지 못하면 해당 인스턴스를 장애 상태로 간주한다. 기본적으로 이 임계 시간은 90초로, 3회의 하트비트 누락 후에 인스턴스가 레지스트리에서 제거될 수 있도록 한다. 이 메커니즘은 네트워크 지연이나 일시적인 장애 상황에서도 서비스 목록의 정확성을 보장한다.
클라이언트는 하트비트 갱신에 실패할 경우, 등록 절차를 재시도하여 서버에 다시 자신을 등록하려고 시도한다. 이 설계는 분산 시스템에서 발생할 수 있는 일시적인 통신 단절이나 서버 재시작과 같은 상황에서도 시스템의 자가 치유 능력을 제공한다. 따라서 마이크로서비스 아키텍처의 전반적인 가용성과 탄력성을 유지하는 데 기여한다.
5.3. 조회 절차
5.3. 조회 절차
Eureka 클라이언트는 애플리케이션 구동 시점에 로컬에 서비스 레지스트리 정보를 캐싱한다. 이 캐시는 주기적으로 Eureka 서버로부터 최신 서비스 목록을 갱신받아 유지된다. 클라이언트가 다른 서비스를 호출해야 할 때는 이 로컬 캐시를 먼저 조회하여 대상 서비스의 실제 네트워크 위치(IP 주소와 포트)를 얻는다.
이러한 클라이언트 사이드 캐싱 방식은 모든 서비스 호출이 Eureka 서버를 거칠 필요가 없게 하므로, 서버에 부하가 집중되는 것을 방지하고 전체 시스템의 내결함성을 높인다. 만약 Eureka 서버에 일시적 장애가 발생하더라도 클라이언트는 캐시된 정보를 기반으로 서비스 호출을 계속할 수 있다.
조회 과정에서 Eureka 클라이언트는 기본적으로 라운드 로빈 알고리즘을 사용하여 동일한 서비스 이름으로 등록된 여러 인스턴스 중 하나를 선택한다. 이를 통해 자체적으로 간단한 로드 밸런싱을 수행할 수 있다. 더 복잡한 라우팅 정책이 필요하다면 Spring Cloud LoadBalancer와 같은 별도의 로드 밸런서 클라이언트와 연동하여 사용한다.
서비스 정보의 갱신 주기는 클라이언트 설정을 통해 조절할 수 있으며, 일반적으로 30초마다 Eureka 서버로부터 전체 레지스트리 정보를 가져와 로컬 캐시를 업데이트한다. 이로 인해 서비스 인스턴스의 상태 변화가 모든 클라이언트에 전파되기까지 최대 30초의 지연이 발생할 수 있다.
5.4. 제거 절차
5.4. 제거 절차
Eureka 서버는 등록된 서비스 인스턴스의 상태를 지속적으로 모니터링하여 비정상적인 인스턴스를 레지스트리에서 제거한다. 이 제거 절차는 주로 두 가지 메커니즘을 통해 이루어진다.
첫 번째는 Eureka 클라이언트의 자발적인 등록 해제다. 서비스 인스턴스가 정상적으로 종료될 때, 스프링 부트 애플리케이션은 셧다운 훅을 실행하여 Eureka 서버에 등록 해제 요청을 보낸다. 이를 통해 서버는 해당 인스턴스를 레지스트리에서 즉시 제거하고, 다른 서비스들이 더 이상 사용 불가능한 인스턴스를 조회하지 않도록 한다.
두 번째는 서버 측의 강제 제거다. 클라이언트는 설정된 주기(기본 30초)마다 서버에 하트비트(갱신 요청)를 보내 자신의 존재를 알린다. 서버는 일정 시간(기본 90초) 동안 특정 인스턴스로부터 하트비트를 받지 못하면 해당 인스턴스를 장애가 발생한 것으로 판단한다. 이후 서버는 주기적으로 실행되는 제거 태스크를 통해 이러한 퇴출 대상 인스턴스들을 레지스트리에서 삭제한다. 이렇게 제거된 인스턴스 정보는 Eureka 클라이언트가 다음 서비스 목록을 갱신할 때 반영되어, 클라이언트 사이드 로드 밸런싱에서 제외된다.
6. 보안
6. 보안
Spring Cloud Netflix Eureka는 기본적으로 보안 기능을 내장하고 있지 않다. 따라서 Eureka 서버와 클라이언트 간의 통신은 기본적으로 암호화되지 않은 HTTP를 사용하며, 인증 메커니즘이 적용되지 않은 상태로 동작한다. 이는 개발 및 테스트 환경에서는 문제가 되지 않을 수 있으나, 프로덕션 환경이나 외부에 노출된 네트워크에서는 심각한 보안 취약점으로 작용할 수 있다.
Eureka를 보안 환경에서 운영하기 위해서는 일반적으로 몇 가지 접근 방식을 취한다. 가장 일반적인 방법은 HTTPS를 통한 통신 암호화와 HTTP 기본 인증을 결합하여 사용하는 것이다. 이를 위해 Eureka 서버와 클라이언트의 설정 파일에 보안 관련 속성을 추가하여, 서로 간의 통신에 사용자 이름과 비밀번호를 요구하도록 구성할 수 있다. 또한, 스프링 시큐리티와 같은 외부 보안 프레임워크를 Eureka 서버 애플리케이션에 통합하여 더욱 세밀한 접근 제어를 구현하는 방법도 널리 사용된다.
또 다른 중요한 보안 고려 사항은 네트워크 보안 차원의 격리이다. Eureka 서버를 사설 네트워크나 가상 사설망 내부에 배치하여 외부 불법 접근을 원천적으로 차단하는 전략이 효과적이다. 이 경우, API 게이트웨이가 외부 요청을 받아 내부 서비스와 Eureka에 대한 프록시 역할을 수행하는 아키텍처가 일반적이다. 이러한 방식은 Eureka 자체의 보안 강화와 더불어 전체 마이크로서비스 아키텍처의 보안 경계를 명확히 하는 데 도움이 된다.
7. 모니터링 및 관리
7. 모니터링 및 관리
Spring Cloud Netflix Eureka는 운영 환경에서 서비스 레지스트리의 상태와 성능을 확인하고 관리하기 위한 모니터링 및 관리 기능을 제공한다. Eureka 서버는 내장된 웹 기반 관리 대시보드를 통해 등록된 모든 서비스 인스턴스, 그 상태, 메타데이터 등을 실시간으로 조회할 수 있는 인터페이스를 제공한다. 이 대시보드는 기본적으로 /eureka 경로에서 접근 가능하며, 운영자는 이를 통해 클러스터의 전반적인 건강 상태와 특정 마이크로서비스 인스턴스의 가용성을 쉽게 파악할 수 있다.
관리 측면에서 Eureka는 REST API를 광범위하게 노출시켜 자동화된 관리와 통합을 가능하게 한다. 예를 들어, 운영 스크립트나 CI/CD 파이프라인에서 이 API를 사용하여 서비스 인스턴스를 수동으로 등록하거나 제거할 수 있다. 또한, 스프링 부트 액추에이터와의 통합을 통해 /actuator/eureka 엔드포인트를 제공하여, 애플리케이션의 건강 정보와 Eureka 클라이언트의 현재 상태를 모니터링 도구에 노출시키는 것이 일반적이다.
Eureka 서버와 클라이언트의 내부 동작은 구성 가능한 다양한 메트릭을 통해 관찰할 수 있다. 주요 메트릭으로는 초당 서비스 등록 및 갱신 요청 수, 현재 등록된 인스턴스 수, 피어 투 피어 복제 상태 등이 있으며, 이러한 메트릭은 마이크로미터 또는 스프링 부트 액추에이터 메트릭을 통해 수집되어 프로메테우스, 그라파나와 같은 모니터링 시스템으로 전송될 수 있다. 이를 통해 장애 조기 발견 및 용량 계획에 활용된다.
모니터링 요소 | 설명 | 일반적인 도구/방법 |
|---|---|---|
서비스 인스턴스 목록 | 등록된 모든 인스턴스의 ID, 상태, 메타데이터 확인 | Eureka 관리 대시보드( |
서버 및 클라이언트 상태 | 애플리케이션의 건강 상태, Eureka 연동 상태 | 스프링 부트 액추에이터 엔드포인트( |
운영 메트릭 | 등록/갱신 요청률, 인스턴스 수, 캐시 효율 등 | 마이크로미터, 프로메테우스, 그라파나 |
로그 분석 | 서비스 발견 실패, 통신 오류 등의 문제 진단 | 애플리케이션 로그 (로그 레벨 조정) |
8. 대안 기술
8. 대안 기술
8.1. Consul
8.1. Consul
Consul은 HashiCorp가 개발한 오픈 소스 서비스 디스커버리 및 서비스 메시 도구이자 키-값 저장소이다. Spring Cloud Netflix Eureka가 순수하게 서비스 디스커버리와 로드 밸런싱에 초점을 맞춘 반면, Consul은 더 넓은 범위의 인프라스트럭처 자동화 기능을 제공하는 것이 특징이다. Consul은 서비스 등록과 상태 확인 외에도 분산 시스템을 위한 서비스 구성 관리와 다중 데이터센터 지원을 핵심 기능으로 포함한다.
Consul의 아키텍처는 에이전트 기반으로, 각 서비스 호스트에 설치된 에이전트가 클라이언트 또는 서버 모드로 실행된다. 서버 에이전트들은 래프트 합의 알고리즘을 사용하여 고가용성을 보장하는 클러스터를 형성한다. 모든 서비스 인스턴스는 자신의 로컬 Consul 에이전트에 등록되며, 에이전트는 서버 클러스터에 이 정보를 전파하여 서비스 카탈로그를 유지 관리한다. 이는 Eureka의 피어링 모델과는 다른 접근 방식이다.
Consul은 내장된 DNS 서버 또는 HTTP API를 통해 서비스 발견을 제공한다. 또한, 서비스 구성 정보를 저장하고 동적으로 제공할 수 있는 키-값 저장소를 갖추고 있어, 외부 구성 서버의 역할을 동시에 수행할 수 있다. 보안 측면에서는 ACL과 TLS 암호화를 기본적으로 지원하여 서비스 간 통신과 에이전트 간 통신의 보안을 강화한다.
Spring Cloud 생태계에서는 spring-cloud-starter-consul-discovery 의존성을 통해 Consul을 서비스 디스커버리 구현체로 쉽게 통합할 수 있다. 이 경우 Spring Boot 애플리케이션은 Eureka 클라이언트를 사용할 때와 유사한 방식으로 자동으로 Consul에 등록되고, 다른 서비스의 위치를 Consul로부터 조회하게 된다. 따라서 마이크로서비스 플랫폼에 서비스 디스커버리 이상의 통합 인프라 기능이 필요할 때 Eureka의 대안으로 고려된다.
8.2. Zookeeper
8.2. Zookeeper
주키퍼(ZooKeeper)는 아파치 소프트웨어 재단에서 개발한 오픈 소스 분산 코디네이션 서비스이다. 원래 하둡 생태계의 구성 요소로 설계되었으나, 분산 시스템에서의 구성 관리, 동기화, 네이밍 서비스 등 다양한 코디네이션 작업을 위한 범용 솔루션으로 널리 사용된다. 주키퍼는 서버 노드들로 구성된 앙상블(Ensemble)에서 실행되며, 고가용성과 일관성을 보장하는 분산 합의 알고리즘을 기반으로 동작한다.
주키퍼는 마이크로서비스 아키텍처에서 서비스 디스커버리를 구현하는 데에도 활용될 수 있다. 서비스 인스턴스는 주키퍼의 계층적 네임스페이스(znode)에 자신을 등록하고, 클라이언트는 해당 znode를 조회하여 서비스 위치 정보를 얻는다. 또한, 이펙티브 이벤트를 통해 서비스 인스턴스의 상태 변화를 실시간으로 감지할 수 있다. 그러나 주키퍼는 서비스 디스커버리 외에도 분산 락, 리더 선출, 구성 정보 저장 등 더 포괄적인 코디네이션 기능을 제공하는 것이 특징이다.
스프링 클라우드 넷플릭스 유레카와 비교할 때, 주키퍼는 서비스 디스커버리에 특화된 도구라기보다는 강력한 일관성(CP)을 보장하는 범용 분산 코디네이션 시스템에 가깝다. 이로 인해 설정과 운영이 상대적으로 복잡할 수 있으며, 서비스 디스커버리만을 위한 단순한 사용 사례에서는 과도한 기능을 포함할 수 있다. 반면, 유레카는 서비스 디스커버리와 클라이언트 사이드 로드 밸런싱에 최적화되어 있고, 가용성을 우선시하는(AP) 설계 철학을 가지고 있어 사용이 더 간편한 편이다.
8.3. Nacos
8.3. Nacos
Nacos는 알리바바 그룹이 개발한 오픈소스 플랫폼으로, 마이크로서비스 아키텍처에서 서비스 디스커버리와 설정 관리를 동시에 제공한다. Spring Cloud Netflix Eureka가 주로 서비스 디스커버리에 중점을 둔 반면, Nacos는 서비스 등록 및 발견 기능에 더해 중앙 집중식 설정 관리 서버 역할을 수행한다는 점이 주요 차별점이다. 이로 인해 개발자는 서비스의 네트워크 위치 정보와 애플리케이션 구성 정보를 하나의 플랫폼에서 통합 관리할 수 있다.
Nacos의 아키텍처는 AP와 CP 모델 간의 전환을 지원하는 것으로 알려져 있다. 이는 CAP 정리에 따른 유연성을 의미하며, 서비스 디스커버리 시나리오에서는 가용성을 우선시하는 AP 모드를, 구성 관리와 같은 중요한 설정 정보를 다룰 때는 일관성을 보장하는 CP 모드를 선택할 수 있다. 또한, 도커와 쿠버네티스 같은 현대적인 클라우드 네이티브 환경에 쉽게 통합될 수 있도록 설계되었다.
Nacos는 Spring Cloud Alibaba 프로젝트의 핵심 컴포넌트로 공식적으로 통합되어 있으며, 이는 Spring Cloud 생태계에서 Eureka나 Consul의 대안으로 사용될 수 있음을 의미한다. 내장된 관리 콘솔을 통해 등록된 서비스와 구성 데이터를 시각적으로 모니터링하고 관리할 수 있어 운영 편의성이 높다. 이러한 다기능 통합과 유연성 덕분에, 특히 설정 관리가 필요한 복잡한 마이크로서비스 환경에서 점차 주목받고 있다.
9. 여담
9. 여담
Spring Cloud Netflix Eureka는 Netflix, Inc.가 자사의 클라우드 컴퓨팅 플랫폼에서 사용하던 서비스 디스커버리 도구를 오픈소스화한 것이 시초이다. 이후 Spring Cloud 프로젝트에 통합되면서 자바와 스프링 프레임워크 생태계를 중심으로 마이크로서비스 아키텍처 구축에 널리 활용되는 핵심 컴포넌트가 되었다.
Eureka라는 이름은 고대 그리스어로 "발견하다"라는 의미를 지닌 "εὕρηκα(헤우레카)"에서 유래했다. 이는 아르키메데스가 유명한 원리를 발견하고 외쳤다는 일화에서 비롯된 표현으로, 서비스의 위치를 '발견'한다는 이 도구의 핵심 기능을 잘 상징한다. 이러한 명명은 기술의 기능적 목적을 직관적으로 전달하는 네이밍 컨벤션의 한 예로 볼 수 있다.
기술적 측면에서 Eureka는 REST 기반의 API를 통해 동작하는 비교적 단순하고 가벼운 아키텍처를 지향했다. 이는 당시 복잡한 CP 시스템을 요구하던 Zookeeper 같은 다른 서비스 디스커버리 솔루션과 대비되는 특징이었다. Eureka의 설계 철학은 클라우드 네이티브 환경에서 발생할 수 있는 부분적 장애나 네트워크 분할 상황에서도 서비스 등록 정보를 유지하는 데 중점을 두어, 가용성을 높이는 데 기여했다.
시간이 지나며 Spring Cloud의 공식 지원 단계 변경과 함께, Eureka는 새로운 기능 추가가 중단된 유지 관리 모드에 들어갔다. 이로 인해 많은 조직들이 Consul이나 Nacos 같은 더 활발히 개발되는 대안 기술로 전환하는 추세를 보이고 있다. 그러나 수많은 기존 시스템에서 여전히 운영되고 있으며, 서비스 디스커버리의 기본 개념을 이해하는 데 있어 중요한 역사적이고 교육적인 가치를 지닌 프로젝트로 남아 있다.
